package cn.com.openportal.ffw.common.aspect;

import cn.com.openportal.ffw.cache.utils.CacheUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;

/**
 * @author LeeSon QQ & WX:25901875
 * @version V1.0
 * @Package cn.com.openportal.ffw.common.aspect
 * @create 2020-01-09 11:35
 * @Copyright © 2019 LeeSon QQ & WX:25901875
 */
@Aspect
@Service
public class CacheAspect {
    private static Logger logger = LoggerFactory.getLogger(CacheAspect.class);

    @Autowired
    CacheUtils CacheUtils;

    /**
     * @return void
     * @Title: queryCachePointcut
     * @Description: 定义切点为缓存注解
     **/
    @Pointcut("@within(cn.com.openportal.ffw.common.annotation.CacheAspectAnnotation)")
    public void CachePointcut() {
    }

    @Around("CachePointcut()")
    public Object Interceptor(ProceedingJoinPoint joinPoint) throws Throwable {
        //类名
        String className = joinPoint.getTarget().getClass().getName();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = signature.getName();

        if (methodName.indexOf("getPage") != -1 || methodName.indexOf("getByKey") != -1 || methodName.indexOf("getList") != -1 || methodName.indexOf("getCount") != -1) {
            Method method = signature.getMethod();
            // 参数值
            Object[] args = joinPoint.getArgs();
            ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
            // 参数名
            String[] parameterNames = pnd.getParameterNames(method);

            String p = "";
            for (int i = 0; i < parameterNames.length; i++) {
                p = p + parameterNames[i] + "=" + args[i].toString() + "&";
            }
            String key = methodName + "_" + p;
            Object data = getOrPutCache(joinPoint, className, key);
            if (null != data) {
                return data;
            }
            return joinPoint.proceed();
        } else if (methodName.indexOf("add") != -1 || methodName.indexOf("update") != -1 || methodName.indexOf("delete") != -1) {
            delCache(joinPoint, className, methodName);
            return 1;
        } else {
            // 调用原始方法
            return joinPoint.proceed();
        }
    }

    private Object getOrPutCache(ProceedingJoinPoint joinPoint, String className, String key) throws Throwable {
        Object object = CacheUtils.getCache(className, key);
        if (null != object) {
            // 缓存中获取到数据，直接返回
            return object;
        }
        if (object == null) {
            // 缓存中没有数据，调用原始方法
            object = joinPoint.proceed();
            CacheUtils.putCache(className, key, object);
        }
        return object;
    }

    private void delCache(ProceedingJoinPoint joinPoint, String className, String methodName) throws Throwable {
        // 调用原始方法
        joinPoint.proceed();
        CacheUtils.delCache(className, methodName);
        return;
    }
}
